package com.whq.mvc.service.impl;

import com.whq.mvc.dao.PromoDOMapper;
import com.whq.mvc.entity.PromoDO;
import com.whq.mvc.service.ItemService;
import com.whq.mvc.service.PromoService;
import com.whq.mvc.service.UserService;
import com.whq.mvc.service.model.ItemModel;
import com.whq.mvc.service.model.PromoModel;
import com.whq.mvc.service.model.UserModel;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class PromoServiceImpl implements PromoService {

    @Autowired
    private PromoDOMapper promoDOMapper;

    @Autowired
    private ItemService itemService;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void publishPromo(Integer promoId) {
        PromoDO promoDO = promoDOMapper.selectByPrimaryKey(promoId);
        if (Objects.isNull(promoDO) || promoDO.getItemId() == 0) return;
        ItemModel itemModel = itemService.getItemById(promoDO.getItemId());
        if (!Objects.isNull(itemModel)) {
            redisTemplate.opsForValue().set("promo_item_stock_" + itemModel.getId(), itemModel.getStock());
            //设置可获取令牌数量
            redisTemplate.opsForValue().set("promo_door_count_" + promoId, itemModel.getStock().intValue() * 5);
        }
    }

    @Override
    public String generateSecondKillToken(Integer promoId, Integer itemId, Integer userId) {
        //已售罄
        if (redisTemplate.hasKey("promo_item_stock_invalid_" + itemId)) {
            return null;
        }
        PromoDO promoDO = promoDOMapper.selectByPrimaryKey(promoId);
        PromoModel promoModel = this.convertFromDataObject(promoDO);
        if (Objects.isNull(promoModel)) {
            return null;
        }
        if (promoModel.getStartDate().isAfterNow()) {
            promoModel.setStatus(1);    //活动未开始
        } else if (promoModel.getEndDate().isBeforeNow()) {
            promoModel.setStatus(3);    //活动已结束
        } else {
            promoModel.setStatus(2);    //活动进行中
        }
        if (promoModel.getStatus().intValue() != 2) {
            return null;
        }
        //判断item是否存在
        ItemModel itemModel = itemService.getItemByIdInCache(itemId);   //修改为通过redis缓存获取
        if (Objects.isNull(itemModel)) {
            return null;
        }
        //判断用户是否为空
        UserModel userModel = userService.getUserByIdInCache(userId);   //修改为通过redis缓存获取
        if (Objects.isNull(userModel)) {
            return null;
        }
        //判断可获取令牌数量
        Long doorCount = redisTemplate.opsForValue().increment("promo_door_count_" + promoId, -1);
        if (doorCount < 0) {
            return null;
        }

        String token = UUID.randomUUID().toString().replace("-", "");
        String tokenKey = String.format("promo_token_%s_userId_%s_itemId_%s", promoId, userId, itemId);
        redisTemplate.opsForValue().set(tokenKey, token, 5, TimeUnit.MINUTES);
        return token;
    }

    @Override
    public PromoModel getPromoByItemId(Integer itemId) {
        PromoDO promoDO = promoDOMapper.selectByItemId(itemId);
        PromoModel promoModel = this.convertFromDataObject(promoDO);
        if (Objects.isNull(promoModel)) return null;
        if (promoModel.getStartDate().isAfterNow()) {
            promoModel.setStatus(1);
        } else if (promoModel.getEndDate().isBeforeNow()) {
            promoModel.setStatus(3);
        } else {
            promoModel.setStatus(2);
        }
        return promoModel;
    }

    private PromoModel convertFromDataObject(PromoDO promoDO) {
        if (Objects.isNull(promoDO)) return null;
        PromoModel promoModel = new PromoModel();
        BeanUtils.copyProperties(promoDO, promoModel);
        promoModel.setPromoItemPrice(new BigDecimal(promoDO.getPromoItemPrice()));
        promoModel.setStartDate(new DateTime(promoDO.getStartDate()));
        promoModel.setEndDate(new DateTime(promoDO.getEndDate()));
        return promoModel;
    }
}
